<template>
  <px-dialog v-model="dialogVisible" title="关联分析" width="80%" height="50%" :before-close="handleClose">
    <div class="chart-wrapper">
      <div class="chart-top">
        <div class="chart-top-query">
          <px-date-picker v-model="queryDate" type="datetimerange" range-separator="-" start-placeholder="开始时间" end-placeholder="结束时间" />
          <px-button type="primary" @click="handleQuery">查询</px-button>
        </div>
        <div class="chart-top-select">
          <px-select
            v-model="selectValues"
            class="m-2"
            :disabled="selectDisabled"
            multiple
            collapse-tags
            filterable
            remote
            reserve-keyword
            placeholder="请输入检索内容"
            :remote-method="handleSelectFilter"
            :loading="loading"
            @change="handleSelectChange"
          >
            <px-option v-for="(item, index) in measureOptions" :key="index" :label="item.label" :value="item.value" />
          </px-select>
        </div>
      </div>
      <div class="chart-content">
        <div class="chart-component">
          <chartoption v-if="spcChartsList.length > 0" :SpcAnalysis="spcChartsList" :tabvalue="pointList[0]" :width="'100%'" :height="'270px'" />
          <div v-else>
            <px-empty class="chartsdom" :image-size="200" />
          </div>
        </div>
        <div class="chart-detail">
          <div class="indicator-types">
            <div v-for="item in equipMentList" :key="item.id" class="indicator-type">
              <div class="indicator-type-top">
                <div class="top-item top-left">
                  <div>
                    <div class="check-icon-wrapper" @click="handleCheckChange(item)">
                      <div v-show="!item.checked" class="check-icon" />
                      <div v-show="item.checked" class="check-icon-checked">
                        <px-icon :size="12">
                          <Check />
                        </px-icon>
                      </div>
                    </div>
                    <!-- <px-checkbox v-model="item.checked" @change="handleCheckChange" size="large" /> -->
                  </div>
                  <div class="top-left-value">
                    {{ item.valueUnit }}
                  </div>
                </div>
                <div class="top-item top-center">
                  {{ item.attributeName }}
                </div>
                <div class="top-item top-right">{{ item.attributeIdentify }}</div>
              </div>
              <div class="indicator-type-content">
                <div class="content-left">
                  <div class="content-value">{{ item.detail.last_value }}</div>
                  <div class="content-value">{{ item.detail.last_value }}</div>
                </div>
                <div class="content-right">
                  <div class="content-item">
                    <div class="content-title">最大值</div>
                    <div class="content-value">{{ item.detail.max_value }}</div>
                  </div>
                  <div class="content-item">
                    <div class="content-title">平均值</div>
                    <div class="content-value">{{ item.detail.avg_value }}</div>
                  </div>
                  <div class="content-item">
                    <div class="content-title">最小值</div>
                    <div class="content-value">{{ item.detail.min_value }}</div>
                  </div>
                </div>
              </div>
            </div>
            <div v-for="item in measureSelectedList" :key="item.id" class="indicator-type">
              <div class="indicator-type-top" :style="{ backgroundColor: '#A2B7F4' }">
                <div class="top-item top-left">
                  <div>
                    <div class="check-icon-wrapper" @click="handleMeasureCheckChange(item)">
                      <div v-show="!item.checked" class="check-icon" />
                      <div v-show="item.checked" class="check-icon-checked">
                        <px-icon :size="12">
                          <Check />
                        </px-icon>
                      </div>
                    </div>
                    <!-- <px-checkbox v-model="item.checked" @change="handleMeasureCheckChange" size="large" /> -->
                  </div>
                  <div class="top-left-value">
                    {{ item.measureUnit }}
                  </div>
                </div>
                <div class="top-item top-center">
                  {{ item.measureName }}
                </div>
                <div class="top-item top-right">{{ item.measureCode }}</div>
              </div>
              <div class="indicator-type-content">
                <div class="content-left">
                  <div class="content-value">{{ item.detail?.last_value }}</div>
                  <div class="content-value">{{ item.detail?.last_value }}</div>
                </div>
                <div class="content-right">
                  <div class="content-item">
                    <div class="content-title">最大值</div>
                    <div class="content-value">{{ item.detail.max_value }}</div>
                  </div>
                  <div class="content-item">
                    <div class="content-title">平均值</div>
                    <div class="content-value">{{ item.detail.avg_value }}</div>
                  </div>
                  <div class="content-item">
                    <div class="content-title">最小值</div>
                    <div class="content-value">{{ item.detail.min_value }}</div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </px-dialog>
</template>

<script lang="ts" setup>
import { ref, onMounted, nextTick } from "vue";
import { PxMessageBox } from "px-ui";
import { spcquerySpcAnalysis } from "@/api/spc";
import { http } from "@/utils/http";
import dayjs from "dayjs";
import chartoption from "./chartoption.vue";
//import chartoption from "../../../water/spc/components/chartoption.vue";
type ResultTable = {
  total?: number;
  data?: Array<any>;
};

const currentDate = {
  year: new Date().getUTCFullYear(),
  month: new Date().getMonth(),
  day: new Date().getUTCDate()
};
const queryDate = ref<[Date, Date]>([
  new Date(currentDate.year, currentDate.month, currentDate.day, 0, 0),
  new Date(currentDate.year, currentDate.month, currentDate.day, 23, 59)
]);
const selectValues = ref<string[]>([]);
const selectDisabled = ref(true); //是否可用

/**start 数据加载过程 */
onMounted(() => {
  // handleQuery();
});

//查询测试
const handleQuery = () => {
  selectDisabled.value = true;
  measureList.value = [];
  //右上角列表可以查询的所有数据来源（分批获取）
  getMeasureList(1);
  //通过consumable/listAll查询直接显示的数据
  getConsumableList();
};

//1-查询所有包含耗材的设备列表
const getConsumableList = () => {
  const params = { typeId: "593", className: "MACHINE", devType: "MAU" };
  queryConsumableList(params).then(res => {
    getEquipment(res?.ffuList);
  });
};

//2-查询单个设备属性
const getEquipment = ffuList => {
  const queryPromise = [];
  for (let i = 0; i < ffuList.length; i++) {
    queryPromise.push(getEquipmentPromise(ffuList[i].ffuCode));
  }
  Promise.allSettled(queryPromise).then(res => {
    setEquipMentData(res);
  });
};

const setEquipMentData = res => {
  let resValues = [];
  for (let i = 0; i < res.length; i++) {
    if (res[i].status === "fulfilled" && res[i].value.length > 0) {
      for (let j = 0; j < res[i].value.length; j++) {
        let item = res[i].value[j];
        let newItem: Equipment = {
          id: item.id,
          eqpId: item.eqpId,
          positionNum: item.positionNum,
          attributeIdentify: item.attributeIdentify,
          attributeName: item.attributeName,
          attributeType: item.attributeType,
          valueUnit: item.valueUnit,
          checked: false,
          detail: {}
        };
        resValues.push(newItem);
      }
    }
  }
  equipMentList.value = resValues;
  excuteScadaIndicatorByEquipment(30);
};

const getEquipmentPromise = ffuCode => {
  return new Promise((resolve, reject) => {
    let params = {
      eqpId: ffuCode, //待确认
      attributeType: "DYNAMIC"
      // hidden: 1
    };

    queryByEquipmentId(params)
      .then(res => {
        resolve(res);
      })
      .catch(err => {
        reject(err);
      });
  });
};

//处理指标数据->数据来源是equipmentAttribute/queryList接口
const excuteScadaIndicatorByEquipment = batchSize => {
  let positionNumList = [];
  equipMentList.value.forEach(p => {
    positionNumList.push(p.positionNum);
  });
  // 计算总批次数
  const totalBatches = Math.ceil(equipMentList.value?.length / batchSize);
  for (let i = 0; i < totalBatches; i++) {
    // 计算当前批次的起始和结束索引
    const startIndex = i * batchSize;
    const endIndex = Math.min(startIndex + batchSize, equipMentList.value?.length);
    // 获取当前批次的数据
    const batchData = positionNumList.slice(startIndex, endIndex);
    // 查询每个设备的详细数据
    getScadaIndicator(batchData).then(res => {
      const scadaData = res.rows;
      //fot test
      equipMentList.value.forEach(item => {
        const pointData = scadaData.filter(p => p.point === item.positionNum);
        if (pointData.length > 0) {
          item.detail = {
            last_value: pointData[0].last_value,
            avg_value: pointData[0].avg_value,
            min_value: pointData[0].min_value,
            max_value: pointData[0].max_value
          };
        } else {
          item.detail = {
            last_value: 0,
            avg_value: 0,
            min_value: 0,
            max_value: 0
          };
        }
      });
    });
  }
};
//处理指标数据->数据来源是measure/pageMeasureList接口
const excuteScadaIndicatorByMeasureList = () => {
  let positionNumList = [];
  measureSelectedList.value.forEach(p => {
    positionNumList.push(p.measureCode);
  });
  // 查询每个设备的详细数据
  getScadaIndicator(positionNumList).then(res => {
    const scadaData = res.rows;
    //fot test
    measureSelectedList.value.forEach(item => {
      const pointData = scadaData.filter(p => p.point === item.measureCode);
      if (pointData.length > 0) {
        item.detail = {
          last_value: pointData[0].last_value,
          avg_value: pointData[0].avg_value,
          min_value: pointData[0].min_value,
          max_value: pointData[0].max_value
        };
      } else {
        item.detail = {
          last_value: 0,
          avg_value: 0,
          min_value: 0,
          max_value: 0
        };
      }
    });
  });
};

//3-查询单个设备属性的数据指标
const getScadaIndicator = positionNumList => {
  // let params = {
  //   bucketWidth: 0,
  //   bucketUnit: "",
  //   startTime: "",
  //   endTime: "",
  //   // point: [],
  //   point: positionNumList,
  //   indicators: ["AVG", "MAX", "MIN"], //统计指标常量：AVG/MAX/MIN/COUNT/FIRST/LAST/SUM
  //   pageNum: 1,
  //   pageSize: 9999,
  //   contentType: ""
  // };
  let startTime = "";
  let endTime = "";
  if (queryDate.value !== null) {
    startTime = dayjs(queryDate.value[0]).format("YYYY-MM-DD HH:mm:ss");
    endTime = dayjs(queryDate.value[1]).format("YYYY-MM-DD HH:mm:ss");
  } else {
    startTime = dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss");
    endTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
  }
  let params = {
    bucketWidth: 60,
    bucketUnit: "minutes",
    startTime: startTime,
    endTime: endTime,
    // point: ["T10_TotW", "1A-4-MAU-AH-005", "1A-4-MAU-AH-004"],
    point: positionNumList,
    indicators: ["LAST", "AVG", "MAX", "MIN"],
    pageNum: 1,
    pageSize: 999,
    contentType: "LIST"
  };
  return new Promise((resolve, reject) => {
    queryScadaIndicator(params).then(res => {
      resolve(res);
    });
  });
};

//分批加载所有的measure数据
const getMeasureList = pageNum => {
  doGetMeasureList(pageNum).then(res => {
    measureList.value = [...measureList.value, ...res.data];
    if (res?.pages > pageNum) {
      getMeasureList(pageNum + 1);
    } else {
      selectDisabled.value = false;
    }
  });
};

//4-查询单个设备属性的数据指标
const doGetMeasureList = pageNum => {
  let params = {
    className: "MACHINE",
    pageNum: pageNum,
    pageSize: 2000
  };
  return new Promise((resolve, reject) => {
    queryMeasureList(params).then(res => {
      resolve(res);
    });
  });
};

//1-查询所有包含耗材的设备列表
const queryConsumableList = (data?: object) => {
  return http.request<ResultTable>("post", `/operation/api/v1/operation/consumable/listAll`, {
    data
  });
};
//2-查询单个设备属性
const queryByEquipmentId = (data?: object) => {
  // return http.request<ResultTable>("post", `/digitaltwins/api/v1/equipmentAttribute/queryByEquipmentId`, {
  //   data
  // });
  return http.request<ResultTable>("post", `/digitaltwins/api/v1/equipmentAttribute/queryList`, {
    data
  });
};
//3-查询时序库中的Scada指标数据
const queryScadaIndicator = (data?: object) => {
  return http.request<ResultTable>("post", `/data/api/v1/dataQuery/queryScadaIndicator`, {
    data
  });
};

//4-查询点位数据
const queryMeasureList = (data?: object) => {
  return http.request<ResultTable>("post", `/account/api/v1/measure/pageMeasureList`, {
    data
  });
};

/**end 数据加载过程 */

/**start 数据交互&数据处理过程 */

type Equipment = {
  id: number;
  eqpId: string;
  positionNum: string;
  attributeIdentify: string;
  attributeName: string;
  attributeType: string;
  valueUnit: string;
  checked: boolean;
  detail: object;
};

const equipMentList = ref<Equipment[]>([]); //所有设备列表
const measureList = ref([]); //通过点位查询得到的数据（所有点位数据内容）
const measureFilterList = ref([]); //通过select:remote-method方法检索出来的数据
const measureOptions = ref([]); //measureList转化得到select列表数据，用于select组件的展示
const measureSelectedList = ref<any[]>([]); //从select-measureFilterList数据集中选择的点位
const loading = ref(false);

const pointList = ref([]); //point数据
const pointListByEquipment = ref([]); //从设备信息获取的point数据
const pointListByMeasure = ref([]); //从点位信息获取的point数据
const spcChartsList = ref([]); //echart展示数据

//select搜索功能
const debounce = (fn, delay = 0) => {
  let timerId = null;
  return function (...args) {
    clearTimeout(timerId);
    timerId = setTimeout(() => {
      fn.apply(null, args);
    }, delay);
  };
};

const doSelectFilter = query => {
  if (query) {
    loading.value = true;
    measureFilterList.value = measureList.value.filter(p => {
      return p.measureCode.indexOf(query) > -1 || p.measureCode.toLowerCase().indexOf(query) > -1;
    });
    //禁止过多数据渲染
    if (measureFilterList.value.length > 100) {
      measureFilterList.value = measureFilterList.value.slice(0, 100);
    }
    setSelectOptions(measureFilterList.value);
    loading.value = false;
  }
};
const handleSelectFilter = debounce(doSelectFilter, 200);

//设置右上角的列表内容
const setSelectOptions = list => {
  measureOptions.value = [];
  for (let i = 0; i < list.length; i++) {
    measureOptions.value.push({
      value: list[i].id,
      label: list[i].measureCode
    });
  }
};
//select 切换,更新显示在右侧的选择类型
const handleSelectChange = () => {
  let measureSelectedListNew = [];
  for (let i = 0; i < selectValues.value.length; i++) {
    let targetId = selectValues.value[i];
    const indexInSelectedList = measureSelectedList.value.findIndex(p => p.id === targetId);
    if (indexInSelectedList > -1) {
      //该数据已经选择
      measureSelectedListNew.push(measureSelectedList.value[indexInSelectedList]);
    } else {
      //新的数据
      const indexInFilterList = measureFilterList.value.findIndex(p => p.id === targetId);
      if (indexInFilterList !== -1) {
        let options = measureFilterList.value.filter(p => p.id === targetId);
        options.forEach(p => {
          p.checked = false;
          if (p.measureName == null || p.measureName == "") {
            p.measureName = "未知";
          }
        });
        measureSelectedListNew = [...measureSelectedListNew, ...options];
      }
    }
  }
  measureSelectedList.value = measureSelectedListNew;
  excuteScadaIndicatorByMeasureList();
};

//checkbox选择项切换，更新显示echart图表的数据
const handleCheckChange = item => {
  item.checked = !item.checked;
  pointListByEquipment.value = [];
  for (let i = 0; i < equipMentList.value.length; i++) {
    if (equipMentList.value[i].checked) {
      pointListByEquipment.value.push(equipMentList.value[i].eqpId);
    }
  }
  querySpcAnalysis();
};
const handleMeasureCheckChange = item => {
  nextTick(() => {
    item.checked = !item.checked;

    pointListByMeasure.value = [];
    for (let i = 0; i < measureSelectedList.value.length; i++) {
      if (measureSelectedList.value[i].checked) {
        pointListByMeasure.value.push(measureSelectedList.value[i].measureCode);
      }
    }
    querySpcAnalysis();
  });
};

// spc指标曲线查询
const querySpcAnalysis = async () => {
  pointList.value = [...pointListByEquipment.value, ...pointListByMeasure.value];
  const params = getSpcAnalysisParams();
  const res = await spcquerySpcAnalysis(params, () => {});
  spcChartsList.value = res;
};
//spc指标曲线查询-参数获取
const getSpcAnalysisParams = () => {
  let startTime = "";
  let endTime = "";
  if (queryDate.value !== null) {
    startTime = dayjs(queryDate.value[0]).format("YYYY-MM-DD HH:mm:ss");
    endTime = dayjs(queryDate.value[1]).format("YYYY-MM-DD HH:mm:ss");
  } else {
    startTime = dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss");
    endTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
  }
  const timePeriod = "minutes";
  //const timePeriod = "hour";
  return { startTime, endTime, timePeriod, pointList: pointList.value };
};
/**end 数据交互&数据处理过程 */

const dialogVisible = ref(false);

const handleOpen = () => {
  dialogVisible.value = true;
  handleQuery();
};

const handleClose = (done: () => void) => {
  PxMessageBox.confirm("确认关闭?")
    .then(() => {
      done ? done() : (dialogVisible.value = false);
    })
    .catch(() => {
      // catch error
    });
};

defineExpose({
  handleOpen
});
</script>
<style lang="scss" scoped>
.chart-wrapper {
  min-height: 360px;

  .chart-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;

    .chart-top-select {
      width: 35%;

      :deep(.px-select) {
        width: 100%;
      }
    }

    .chart-top-query {
      display: flex;
      align-items: center;

      :deep(.px-button) {
        margin-left: 16px;
      }
    }
  }

  .chart-content {
    display: flex;
    justify-content: space-between;
    height: 100%;

    .chart-component {
      width: 65%;
      height: 100%;

      .chartsdom {
        width: 100%;
        height: 270px;
        margin-top: 60px;
        background: white;
      }
    }

    .chart-detail {
      width: 35%;
      margin-top: -8px;
      margin-left: 16px;
    }
  }
}

.indicator-types {
  max-height: 346px;
  overflow: hidden auto;

  .indicator-type {
    margin-bottom: 8px;
    border: 1px solid #f2f5f7;
    border-radius: 4px;

    .indicator-type-top {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 4px 8px;
      background-color: #62a8ec;

      .top-item {
        width: 33.33%;
        padding: 0 4px;
        overflow: hidden;
        font-size: 14px;
        color: rgb(0 0 0 / 80%);
        text-wrap: nowrap;
      }

      .top-left {
        display: inline-flex;
        align-items: center;
        justify-content: flex-start;

        .top-left-value {
          margin-left: 4px;
        }
      }

      .top-center {
        font-weight: 500;
      }

      .top-right {
        display: flex;
        justify-content: flex-end;
      }
    }

    .indicator-type-content {
      display: flex;
      padding: 4px 8px;
      font-size: 12px;
      background-color: #fff;

      .content-left {
        display: flex;
        align-items: center;
        justify-content: space-around;
        width: 40%;
      }

      .content-right {
        display: flex;
        justify-content: space-around;
        width: 60%;
        text-align: center;
      }

      .content-value {
        font-weight: 500;
        color: rgb(0 0 0 / 80%);
      }

      .context-title {
        color: #909399;
      }
    }
  }
}

.check-icon-wrapper {
  width: 16px;
  height: 16px;
  cursor: pointer;

  .check-icon {
    width: inherit;
    height: inherit;
    background-color: #fff;
    border-radius: 2px;

    &:hover {
      border: 1px solid #3b82f6;
    }
  }

  .check-icon-checked {
    display: flex;
    align-items: center;
    justify-content: center;
    width: inherit;
    height: inherit;
    color: #fff;
    background-color: #3b82f6;
    border-radius: 2px;
  }
}
</style>
